package com.example.hotel.blImpl.hotel;

import com.example.hotel.bl.hotel.HotelService;
import com.example.hotel.bl.hotel.RoomRepoService;
import com.example.hotel.bl.hotel.RoomService;
import com.example.hotel.bl.order.OrderService;
import com.example.hotel.bl.user.AccountService;
import com.example.hotel.data.hotel.HotelImgMapper;
import com.example.hotel.data.hotel.HotelMapper;
import com.example.hotel.enums.HotelStar;
import com.example.hotel.enums.UserType;
import com.example.hotel.po.Hotel;
import com.example.hotel.po.HotelRoom;
import com.example.hotel.po.Order;
import com.example.hotel.po.User;
import com.example.hotel.util.ServiceException;
import com.example.hotel.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class HotelServiceImpl implements HotelService {

    @Autowired
    private HotelMapper hotelMapper;

    @Autowired
    private HotelImgMapper hotelImgMapper;

    @Autowired
    private AccountService accountService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private RoomService roomService;

    @Autowired
    private RoomRepoService roomRepoService;

    @Override
    public void addHotel(HotelVO hotelVO) throws ServiceException {
        User manager = accountService.getUserInfo(hotelVO.getManagerId());
        if (manager == null || !manager.getUserType().equals(UserType.HotelManager)) {
            throw new ServiceException("管理员不存在或者无权限！创建酒店失败！");
        }
        Hotel hotel = new Hotel();
        hotel.setDescription(hotelVO.getDescription());
        hotel.setAddress(hotelVO.getAddress());
        hotel.setHotelName(hotelVO.getName());
        hotel.setPhoneNum(hotelVO.getPhoneNum());
        hotel.setManagerId(hotelVO.getManagerId());
        hotel.setRate(hotelVO.getRate());
        hotel.setBiz_id(hotelVO.getBiz_id());
        hotel.setHotelStar(HotelStar.valueOf(hotelVO.getHotelStar()));
        hotel.setBizRegion(hotelVO.getBizRegion());
        hotelMapper.insertHotel(hotel);
    }

    @Override
    public void updateRoomInfo(Integer hotelId, String roomType, Integer rooms) {
        roomService.updateRoomInfo(hotelId, roomType, rooms);
    }

    @Override
    public int getRoomCurNum(Integer hotelId, String roomType) {
        return roomService.getRoomCurNum(hotelId, roomType);
    }

    //酒店工作人员 B.i
    //
    @Override
    public ResponseVO updateHotelBasicInfo(HotelVO hotelVO) throws ServiceException {
        User manager = accountService.getUserInfo(hotelVO.getManagerId());
        if (manager == null || !manager.getUserType().equals(UserType.HotelManager)) {
            throw new ServiceException("管理员不存在或者无权限！更新酒店失败！");
        }
        Hotel hotel = new Hotel();
        hotel.setId(hotelVO.getId());
        hotel.setDescription(hotelVO.getDescription());
        hotel.setAddress(hotelVO.getAddress());
        hotel.setHotelName(hotelVO.getName());
        hotel.setPhoneNum(hotelVO.getPhoneNum());
        hotel.setManagerId(hotelVO.getManagerId());
        hotel.setRate(hotelVO.getRate());
        hotel.setBiz_id(hotelVO.getBiz_id());
        hotel.setHotelStar(HotelStar.valueOf(hotelVO.getHotelStar()));
        hotel.setBizRegion(hotelVO.getBizRegion());
        if (hotelMapper.updateHotelBasicInfo(hotel) > 0) {
            return ResponseVO.buildSuccess(true);
        } else {
            return ResponseVO.buildFailure("更新失败，酒店可能不存在");
        }
    }

    @Override
    public List<HotelVO> retrieveHotelDetailsByPos(PositionVO positionVO) {
        return hotelMapper.selectByPos(positionVO);
    }

    @Override
    public List<Integer> retrieveHotelIdByUser(Integer userId) {
        return hotelMapper.selectOrderedHotelIds(userId);
    }

    @Override
    public List<HotelWithImgVO> searchHotel(HotelSearchVO searchVO) {
        // 价格区间筛选已做
        // 除房间间数的筛选 是否预定过筛选 之外，全部在SQL中实现
        List<HotelVO> hotelVOS = hotelMapper.searchHotel(searchVO);

        // 房间间数筛选
        // 取得合适hotels之后遍历room_repo表
        Integer roomDemandCnt = searchVO.getRoomDemandCnt();
        if (roomDemandCnt != null) {
            hotelVOS = hotelVOS.stream().filter(hotelVO -> roomRepoService
                    .getSumOfAvailableNumOfPeriod(hotelVO.getId(), searchVO.getBeginDate(), searchVO.getEndDate())
                    >= searchVO.getRoomDemandCnt())
                    .collect(Collectors.toList());
        }

        // 是否已预订的筛选
        if (searchVO.getOrdered() == 1 && searchVO.getUserId() != null) {
            List<Integer> orderedHotels = orderService.getOrderedHotels(searchVO.getUserId());
            hotelVOS = hotelVOS.stream()
                    .filter(hotelVO -> orderedHotels.contains(hotelVO.getId()))
                    .collect(Collectors.toList());
        }

        // 修改：增加hotel_img表
        // 根据拿到的酒店信息，获取酒店图像以展示
        // : 提取重复代码
        return hotelVOWrapper(hotelVOS);
    }

    @Override
    public List<Order> managedOrders(int managerId) {
        return orderService.managedOrders(managerId);
    }

    @Override
    public List<HotelWithImgVO> retrieveHotels() {
        List<HotelVO> hotelVOS = hotelMapper.selectAllHotel();
        // : 提取重复代码
        return hotelVOWrapper(hotelVOS);
    }


    @Override
    public HotelVO retrieveHotelDetails(Integer hotelId) {
        HotelVO hotelVO = hotelMapper.selectById(hotelId);
        List<HotelRoom> rooms = roomService.retrieveHotelRoomInfo(hotelId);
        List<RoomVO> roomVOS = rooms.stream().map(r -> {
            RoomVO roomVO = new RoomVO();
            roomVO.setId(r.getId());
            roomVO.setPrice(r.getPrice());
            roomVO.setRoomType(r.getRoomType().toString());
            roomVO.setCurNum(r.getCurNum());
            roomVO.setTotal(r.getTotal());
            return roomVO;
        }).collect(Collectors.toList());
        hotelVO.setRooms(roomVOS);

        return hotelVO;
    }

    @Override
    public ResponseVO savePic(MultipartFile file, Integer hotelId) {
        if (file.isEmpty()) {
            return ResponseVO.buildFailure("上传失败,请选择文件");
        }

        try {
            InputStream is = file.getInputStream();
            HotelImgVO hotelImgVO = new HotelImgVO();
            hotelImgVO.setHotelId(hotelId);
            byte[] pic = new byte[(int) file.getSize()];
            is.read(pic);
            hotelImgVO.setPic(pic);

            //还没有记录,插入
            if (hotelImgMapper.getPic(hotelId) == null) {
                hotelImgMapper.insertPic(hotelImgVO);
            }
            //存在记录,更新
            else {
                hotelImgMapper.updatePic(hotelImgVO);
            }

        } catch (IOException e) {
            e.printStackTrace();
            return ResponseVO.buildFailure("图片写入失败，请重试");

        }


        return ResponseVO.buildSuccess("上传成功");
    }

    @Override
    public ResponseVO getPic(Integer hotelId) {
        HotelImgVO hotelImgVO = hotelImgMapper.getPic(hotelId);
        if (hotelImgVO == null) return ResponseVO.buildSuccess(null);
        return ResponseVO.buildSuccess(hotelImgVO);
    }

    @Override
    public boolean bindHotelMgr(HotelBindingVO hotelBindingVO) {
        return hotelMapper.bindNewHotelMgr(hotelBindingVO.getHotelId(), hotelBindingVO.getMgrId()) > 0;
    }

    @Override
    public List<HotelVO> selectManagedBy(Integer mgrId) {
        return hotelMapper.selectManagedBy(mgrId);
    }

    // 提取重复代码
    private List<HotelWithImgVO> hotelVOWrapper(List<HotelVO> hotelVOS) {
        List<HotelWithImgVO> hotelImgVOS = new ArrayList<HotelWithImgVO>();
        for (HotelVO hotelVO : hotelVOS
        ) {
            Integer id = hotelVO.getId();
            String name = hotelVO.getName();
            String address = hotelVO.getAddress();
            String biz_id = hotelVO.getBiz_id();
            String hotelStar = hotelVO.getHotelStar();
            Double rate = hotelVO.getRate();
            String description = hotelVO.getDescription();
            String phoneNum = hotelVO.getPhoneNum();
            Integer managerId = hotelVO.getManagerId();
            List<RoomVO> rooms = hotelVO.getRooms();
            String bizRegion = hotelVO.getBizRegion();
            byte[] pic = null;
            HotelImgVO ho = hotelImgMapper.getPic(id);

            if (ho != null) pic = ho.getPic();
            HotelWithImgVO hotelWithImgVO = new HotelWithImgVO(id, name, address, biz_id, hotelStar,
                    rate, description, phoneNum, managerId, rooms, bizRegion, pic);
            hotelImgVOS.add(hotelWithImgVO);
        }
        return hotelImgVOS;
    }
}
